<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>可嵌入组件</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色和字体 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3B82F6',
                        secondary: '#10B981',
                        neutral: '#64748B',
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <!-- 自定义工具类 -->
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .transition-all-300 {
                transition: all 300ms ease-in-out;
            }
        }
    </style>
    
    <style>
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
        
        /* 防止与主项目的样式冲突 */
        :root {
            all: initial;
        }
    </style>
</head>
<body class="font-inter bg-gray-50 text-gray-800 min-h-screen">
    <div id="app" class="flex flex-col h-full">
        <!-- 头部信息 -->
        <header class="bg-primary text-white p-4 shadow-md">
            <div class="flex justify-between items-center">
                <h1 class="text-xl font-bold flex items-center">
                    <i class="fa fa-puzzle-piece mr-2"></i>嵌入组件
                </h1>
                <div id="connection-status" class="flex items-center text-sm">
                    <span id="status-indicator" class="w-2 h-2 rounded-full bg-yellow-400 mr-2"></span>
                    <span>等待连接...</span>
                </div>
            </div>
        </header>
        
        <!-- 主内容区 -->
        <main class="flex-1 p-6 overflow-y-auto">
            <div class="max-w-2xl mx-auto">
                <!-- 信息展示区 -->
                <div class="bg-white rounded-lg shadow-sm p-5 mb-6">
                    <h2 class="text-lg font-semibold mb-4 flex items-center">
                        <i class="fa fa-exchange text-primary mr-2"></i>与主项目通信
                    </h2>
                    
                    <div id="message-log" class="border border-gray-200 rounded-md p-4 h-48 overflow-y-auto mb-4 bg-gray-50">
                        <p class="text-gray-500 text-sm italic">通信日志将显示在这里...</p>
                    </div>
                    
                    <!-- 发送消息表单 -->
                    <div class="flex gap-3">
                        <input 
                            type="text" 
                            id="message-input" 
                            placeholder="输入要发送给主项目的消息..." 
                            class="flex-1 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50"
                        >
                        <button 
                            id="send-button" 
                            class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-md transition-all-300 flex items-center"
                            disabled
                        >
                            <i class="fa fa-paper-plane mr-2"></i>发送
                        </button>
                    </div>
                </div>
                
                <!-- 交互示例区 -->
                <div class="bg-white rounded-lg shadow-sm p-5">
                    <h2 class="text-lg font-semibold mb-4 flex items-center">
                        <i class="fa fa-cogs text-secondary mr-2"></i>交互示例
                    </h2>
                    
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                        <!-- 颜色切换示例 -->
                        <div class="p-4 border border-gray-200 rounded-md">
                            <h3 class="font-medium mb-2">切换主项目颜色</h3>
                            <div class="flex gap-2 flex-wrap">
                                <button data-color="red" class="w-8 h-8 rounded-full bg-red-500 cursor-pointer hover:ring-2 hover:ring-offset-2 hover:ring-gray-300"></button>
                                <button data-color="green" class="w-8 h-8 rounded-full bg-green-500 cursor-pointer hover:ring-2 hover:ring-offset-2 hover:ring-gray-300"></button>
                                <button data-color="blue" class="w-8 h-8 rounded-full bg-blue-500 cursor-pointer hover:ring-2 hover:ring-offset-2 hover:ring-gray-300"></button>
                                <button data-color="purple" class="w-8 h-8 rounded-full bg-purple-500 cursor-pointer hover:ring-2 hover:ring-offset-2 hover:ring-gray-300"></button>
                            </div>
                        </div>
                        
                        <!-- 通知示例 -->
                        <div class="p-4 border border-gray-200 rounded-md">
                            <h3 class="font-medium mb-2">向主项目发送通知</h3>
                            <button id="notify-button" class="bg-secondary hover:bg-secondary/90 text-white px-4 py-2 rounded-md transition-all-300">
                                <i class="fa fa-bell mr-2"></i>发送通知
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </main>
        
        <!-- 底部信息 -->
        <footer class="bg-gray-100 text-neutral p-3 text-center text-sm">
            <p>嵌入组件 v1.0 | 可与主项目实时交互</p>
        </footer>
    </div>

    <script>
        // 配置 - 允许的主项目域名，增强安全性
        const ALLOWED_ORIGINS = [
            'http://localhost:3000',
            'https://your-main-project-domain.com'
        ];
        
        // 消息类型常量，定义通信协议
        const MESSAGE_TYPES = {
            // 从嵌入页面发送到主项目
            SEND_MESSAGE: 'EMBEDDED:SEND_MESSAGE',
            REQUEST_SIZE_CHANGE: 'EMBEDDED:REQUEST_SIZE_CHANGE',
            NOTIFY: 'EMBEDDED:NOTIFY',
            COLOR_CHANGE: 'EMBEDDED:COLOR_CHANGE',
            READY: 'EMBEDDED:READY',
            
            // 从主项目发送到嵌入页面
            RECEIVE_MESSAGE: 'MAIN:SEND_MESSAGE',
            SIZE_CHANGED: 'MAIN:SIZE_CHANGED',
            ACKNOWLEDGE: 'MAIN:ACKNOWLEDGE'
        };
        
        // DOM元素
        const elements = {
            messageInput: document.getElementById('message-input'),
            sendButton: document.getElementById('send-button'),
            messageLog: document.getElementById('message-log'),
            statusIndicator: document.getElementById('status-indicator'),
            connectionStatus: document.getElementById('connection-status'),
            notifyButton: document.getElementById('notify-button'),
            colorButtons: document.querySelectorAll('[data-color]')
        };
        
        // 状态管理
        const state = {
            connected: false,
            parentOrigin: null,
            logMessages: []
        };
        
        // 初始化
        function init() {
            // 设置事件监听器
            setupEventListeners();
            
            // 向主项目发送准备就绪消息
            sendReadyMessage();
        }
        
        // 设置事件监听器
        function setupEventListeners() {
            // 监听来自主项目的消息
            window.addEventListener('message', handleParentMessage);
            
            // 发送消息按钮点击事件
            elements.sendButton.addEventListener('click', sendMessageToParent);
            
            // 输入框回车发送消息
            elements.messageInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') {
                    sendMessageToParent();
                }
            });
            
            // 通知按钮点击事件
            elements.notifyButton.addEventListener('click', () => {
                sendNotificationToParent('来自嵌入组件的通知消息！');
            });
            
            // 颜色按钮点击事件
            elements.colorButtons.forEach(button => {
                button.addEventListener('click', () => {
                    const color = button.getAttribute('data-color');
                    sendColorChangeRequest(color);
                });
            });
            
            // 监听窗口大小变化，通知主项目
            window.addEventListener('resize', () => {
                notifyParentOfSize();
            });
        }
        
        // 处理来自主项目的消息
        function handleParentMessage(event) {
            // 验证消息来源
            if (!isAllowedOrigin(event.origin)) {
                logMessage(`拒绝来自未授权域名的消息: ${event.origin}`, 'error');
                return;
            }
            
            // 记录父级域名，用于后续通信
            if (!state.parentOrigin) {
                state.parentOrigin = event.origin;
                setConnected(true);
                logMessage(`已连接到主项目: ${event.origin}`, 'info');
            }
            
            // 验证消息格式
            if (!event.data || !event.data.type) {
                logMessage('收到格式不正确的消息', 'error');
                return;
            }
            
            // 处理不同类型的消息
            switch (event.data.type) {
                case MESSAGE_TYPES.RECEIVE_MESSAGE:
                    logMessage(`收到主项目消息: ${event.data.payload}`, 'receive');
                    // 发送确认收到消息
                    sendAcknowledge(event.data.id);
                    break;
                    
                case MESSAGE_TYPES.SIZE_CHANGED:
                    logMessage(`主项目调整了尺寸: ${event.data.payload.width}x${event.data.payload.height}`, 'info');
                    break;
                    
                default:
                    logMessage(`收到未知类型的消息: ${event.data.type}`, 'warning');
            }
        }
        
        // 向主项目发送消息
        function sendMessageToParent() {
            const message = elements.messageInput.value.trim();
            if (!message) return;
            
            if (!state.connected) {
                logMessage('尚未连接到主项目，无法发送消息', 'error');
                return;
            }
            
            const messageId = generateMessageId();
            const payload = {
                id: messageId,
                type: MESSAGE_TYPES.SEND_MESSAGE,
                payload: message,
                timestamp: new Date().toISOString()
            };
            
            // 发送消息
            window.parent.postMessage(payload, state.parentOrigin);
            logMessage(`发送消息到主项目: ${message}`, 'send');
            
            // 清空输入框
            elements.messageInput.value = '';
        }
        
        // 向主项目发送通知
        function sendNotificationToParent(message) {
            if (!state.connected) {
                logMessage('尚未连接到主项目，无法发送通知', 'error');
                return;
            }
            
            const messageId = generateMessageId();
            const payload = {
                id: messageId,
                type: MESSAGE_TYPES.NOTIFY,
                payload: message,
                timestamp: new Date().toISOString()
            };
            
            window.parent.postMessage(payload, state.parentOrigin);
            logMessage(`发送通知到主项目: ${message}`, 'send');
        }
        
        // 发送颜色变更请求
        function sendColorChangeRequest(color) {
            if (!state.connected) {
                logMessage('尚未连接到主项目，无法发送颜色变更请求', 'error');
                return;
            }
            
            const messageId = generateMessageId();
            const payload = {
                id: messageId,
                type: MESSAGE_TYPES.COLOR_CHANGE,
                payload: color,
                timestamp: new Date().toISOString()
            };
            
            window.parent.postMessage(payload, state.parentOrigin);
            logMessage(`请求主项目切换颜色为: ${color}`, 'send');
        }
        
        // 发送准备就绪消息
        function sendReadyMessage() {
            const messageId = generateMessageId();
            const payload = {
                id: messageId,
                type: MESSAGE_TYPES.READY,
                payload: {
                    width: window.innerWidth,
                    height: window.innerHeight,
                    version: '1.0.0'
                },
                timestamp: new Date().toISOString()
            };
            
            // 向所有可能的父级发送准备消息（初始状态下还不知道具体origin）
            window.parent.postMessage(payload, '*');
            logMessage('已发送准备就绪消息', 'info');
        }
        
        // 通知主项目当前尺寸
        function notifyParentOfSize() {
            if (!state.connected) return;
            
            const messageId = generateMessageId();
            const payload = {
                id: messageId,
                type: MESSAGE_TYPES.REQUEST_SIZE_CHANGE,
                payload: {
                    width: window.innerWidth,
                    height: window.innerHeight
                },
                timestamp: new Date().toISOString()
            };
            
            window.parent.postMessage(payload, state.parentOrigin);
        }
        
        // 发送确认收到消息
        function sendAcknowledge(messageId) {
            if (!state.connected) return;
            
            const payload = {
                id: generateMessageId(),
                type: MESSAGE_TYPES.ACKNOWLEDGE,
                payload: {
                    acknowledgedId: messageId
                },
                timestamp: new Date().toISOString()
            };
            
            window.parent.postMessage(payload, state.parentOrigin);
        }
        
        // 记录消息到日志
        function logMessage(message, type = 'info') {
            // 保存到日志数组
            state.logMessages.push({
                message,
                type,
                timestamp: new Date()
            });
            
            // 限制日志长度
            if (state.logMessages.length > 50) {
                state.logMessages.shift();
            }
            
            // 更新UI
            renderMessageLog();
        }
        
        // 渲染消息日志
        function renderMessageLog() {
            elements.messageLog.innerHTML = '';
            
            if (state.logMessages.length === 0) {
                elements.messageLog.innerHTML = '<p class="text-gray-500 text-sm italic">通信日志将显示在这里...</p>';
                return;
            }
            
            state.logMessages.forEach(entry => {
                const logItem = document.createElement('div');
                logItem.className = 'mb-2 pb-2 border-b border-gray-100 last:border-0 last:mb-0 last:pb-0';
                
                const timeSpan = document.createElement('span');
                timeSpan.className = 'text-xs text-gray-400 mr-2';
                timeSpan.textContent = entry.timestamp.toLocaleTimeString();
                
                const messageSpan = document.createElement('span');
                
                // 根据消息类型设置样式
                switch (entry.type) {
                    case 'send':
                        messageSpan.className = 'text-blue-600';
                        messageSpan.innerHTML = `<i class="fa fa-arrow-up text-xs mr-1"></i> ${entry.message}`;
                        break;
                    case 'receive':
                        messageSpan.className = 'text-green-600';
                        messageSpan.innerHTML = `<i class="fa fa-arrow-down text-xs mr-1"></i> ${entry.message}`;
                        break;
                    case 'error':
                        messageSpan.className = 'text-red-600';
                        messageSpan.innerHTML = `<i class="fa fa-exclamation-circle text-xs mr-1"></i> ${entry.message}`;
                        break;
                    case 'warning':
                        messageSpan.className = 'text-yellow-600';
                        messageSpan.innerHTML = `<i class="fa fa-exclamation-triangle text-xs mr-1"></i> ${entry.message}`;
                        break;
                    default:
                        messageSpan.className = 'text-gray-700';
                        messageSpan.innerHTML = `<i class="fa fa-info-circle text-xs mr-1"></i> ${entry.message}`;
                }
                
                logItem.appendChild(timeSpan);
                logItem.appendChild(messageSpan);
                elements.messageLog.appendChild(logItem);
            });
            
            // 滚动到底部
            elements.messageLog.scrollTop = elements.messageLog.scrollHeight;
        }
        
        // 设置连接状态
        function setConnected(connected) {
            state.connected = connected;
            
            if (connected) {
                elements.statusIndicator.className = 'w-2 h-2 rounded-full bg-green-400 mr-2';
                elements.connectionStatus.innerHTML = '<span class="w-2 h-2 rounded-full bg-green-400 mr-2 inline-block"></span><span>已连接到主项目</span>';
                elements.sendButton.disabled = false;
                elements.sendButton.classList.remove('opacity-50', 'cursor-not-allowed');
                elements.sendButton.classList.add('hover:bg-primary/90');
            } else {
                elements.statusIndicator.className = 'w-2 h-2 rounded-full bg-yellow-400 mr-2';
                elements.connectionStatus.innerHTML = '<span class="w-2 h-2 rounded-full bg-yellow-400 mr-2 inline-block"></span><span>等待连接...</span>';
                elements.sendButton.disabled = true;
                elements.sendButton.classList.add('opacity-50', 'cursor-not-allowed');
                elements.sendButton.classList.remove('hover:bg-primary/90');
            }
        }
        
        // 验证来源是否被允许
        function isAllowedOrigin(origin) {
            return true;
            // 开发环境下允许所有来源（方便测试）
            // if (process.env.NODE_ENV === 'development') {
            //     return true;
            // }
            
            // return ALLOWED_ORIGINS.includes(origin);
        }
        
        // 生成唯一消息ID
        function generateMessageId() {
            return Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
        }
        
        // 初始化应用
        document.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html>
